package com.itmck.common.easyexcel;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itmck.common.util.SpringIOCUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Slf4j
public class BatchReadListener<T, R> extends AnalysisEventListener<T> {
    /**
     * 单个处理数据量，经测试1000条数据效果较好
     */
    public static int BATCH_COUNT = 500;
    private boolean flag = false;
    /**
     * 数据的临时存储
     */
    private List<T> cachedDataList = new ArrayList<>(BATCH_COUNT);
    /**
     * consumer
     */
    private Consumer<List<T>> consumer;
    private Class<R> userClass;
    private BaseMapper<R> baseMapper;
    private SqlSessionFactory sqlSessionFactory;

    public BatchReadListener(Consumer<List<T>> consumer) {
        this.consumer = consumer;
    }


    public BatchReadListener(BaseMapper<R> baseMapper, Class<R> userClass) {
        this.baseMapper = baseMapper;
        this.userClass = userClass;
        this.flag = true;
        sqlSessionFactory = SpringIOCUtil.getBean(SqlSessionFactory.class);
    }

    /**
     * 针对excel读取一行走一次此方法
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        cachedDataList.add(data);
        if (cachedDataList.size() >= BATCH_COUNT) {
            log.info("读取数据量:{}", cachedDataList.size());
            if (flag) {
                this.saveBatch();
            } else {
                consumer.accept(cachedDataList);
            }
            cachedDataList = new ArrayList<>(BATCH_COUNT);
        }
    }

    /**
     * 所有数据读取完成之后调用此方法
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

        //解决不满足一个默认BATCH_COUNT的数量
        if (CollectionUtils.isNotEmpty(cachedDataList)) {
            //处理剩余的数据
            log.info("读取剩余数据量>>>>>>>:{}", cachedDataList.size());
            if (flag) {
                this.saveBatch();
            } else {
                consumer.accept(cachedDataList);
            }
        }
    }

    private void saveBatch() {
        //获取SqlSessionFactory并设置执行器类型为批量，设置事物自动提交为false
        log.info("执行批量插入>>>");
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        try {
            cachedDataList.forEach(dat -> {
                R r = BeanUtil.copyProperties(dat, userClass);
                baseMapper.insert(r);
            });
            sqlSession.commit();//提交事物
        } catch (Exception e) {
            sqlSession.rollback();//回滚事物
        } finally {
            sqlSession.clearCache();//清理缓存
        }

    }

}
